package com.serenegiant.service;

import android.annotation.SuppressLint;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import com.friendlyarm.FriendlyThings.BoardType;
import com.friendlyarm.FriendlyThings.GPIOEnum;
import com.friendlyarm.FriendlyThings.HardwareControler;
import com.serenegiant.usbcameratest4.BuildConfig;

import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

public class GPIO {

    private Context context = null;
    private String TAG = "GPIO";

    public GPIO( Context context ){
        this.context = context;
    }
    /**
     * GPIO
     */
    private Map<String, Integer> demoGPIOPins = new HashMap<String, Integer>();
    private Timer timer = new Timer();
    private int TIME_TRICK = 2000;
    private boolean DEBUG = BuildConfig.LOG_DEBUG;

    private long upKeyTime = 0;
    private long downKeyTime = 0;
    private long leftKeyTime = 0;
    private long rightKeyTime = 0;
    private long centerKeyTime = 0;

    public void init(){
        int boardType = HardwareControler.getBoardType();
        if (boardType == BoardType.NanoPC_T4) {
            demoGPIOPins.put("Pin11", 33);
            demoGPIOPins.put("Pin12", 50);
            demoGPIOPins.put("Pin15", 36);
            demoGPIOPins.put("Pin16", 54);
            demoGPIOPins.put("Pin18", 55);
        }

        if (demoGPIOPins.size() == 0) {
            Toast.makeText( context , String.format("Not found any GPIO pin."),
                    Toast.LENGTH_SHORT).show();
        } else {
            // export all pins
            for (Integer sysPinNum: demoGPIOPins.values()) {
                if (HardwareControler.exportGPIOPin(sysPinNum) != 0) {
                    Toast.makeText( context , String.format("exportGPIOPin(%d) failed!", sysPinNum),
                            Toast.LENGTH_SHORT).show();
                }
                HardwareControler.setGPIODirection( sysPinNum , GPIOEnum.IN );
                HardwareControler.setGPIOValue( sysPinNum , GPIOEnum.HIGH );
                int currentDirection = HardwareControler.getGPIODirection(sysPinNum);
                int val = HardwareControler.getGPIOValue( sysPinNum );
                Log.v(TAG, String.format("GPIO(%d) == %d , %d ", sysPinNum, currentDirection , val));
            }

            timer.schedule(init_task, 200, 200);
        }

    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    timer.cancel();
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private TimerTask init_task = new TimerTask() {
        public void run() {
            StringBuilder builder = new StringBuilder();
            for (final Integer sysPinNum : demoGPIOPins.values()) {
                final int currentDirection = HardwareControler.getGPIODirection(sysPinNum);
                final int val = HardwareControler.getGPIOValue(sysPinNum);
                builder.append( "[" + sysPinNum + "]=" + val + " , ");
                //Log.v(TAG, String.format("getGPIODirection(%d) IN %d", sysPinNum , val));
                if ( currentDirection == GPIOEnum.IN ) {
                    long nowTime = System.currentTimeMillis();
                    if( sysPinNum == 55 ) {
                        if( upKeyTime == 0 && val == GPIOEnum.LOW )
                        {
                            upKeyTime = System.currentTimeMillis();
                            //toastAlert( sysPinNum , val , "按下" );
                        }
                        else if( upKeyTime > 0 && val == GPIOEnum.HIGH )
                        {
                            if( nowTime - upKeyTime < TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent(KeyEvent.KEYCODE_DPAD_UP);
                                    }
                                });
                                toastAlert( sysPinNum , val , "短按 上 ts=" + (nowTime - upKeyTime) );
                            } else if( nowTime - upKeyTime >= TIME_TRICK ) {
                                //onKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
                                //模式
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent(KeyEvent.KEYCODE_BUTTON_L1);   //showSetting();
                                    }
                                });
                                toastAlert( sysPinNum , val , "长按 打开设置 ts=" + (nowTime - upKeyTime) );
                            }
                            upKeyTime = 0;
                        }
                    }

                    if( sysPinNum == 54 ) {
                        if( downKeyTime == 0 && val == GPIOEnum.LOW )
                        {
                            downKeyTime = System.currentTimeMillis();
                            //Log.v(TAG, String.format("GPIO(%d) IN %d ,按下 ", sysPinNum , val ));
                        }
                        else if( downKeyTime > 0 && val == GPIOEnum.HIGH )
                        {
                            if( nowTime - downKeyTime < TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN);
                                    }
                                });
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 短按 下", sysPinNum , val , nowTime - downKeyTime ));
                                toastAlert( sysPinNum , val , "短按 下 ts=" + (nowTime - downKeyTime) );
                            } else if( nowTime - downKeyTime >= TIME_TRICK ) {
                                //录像
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
//                                        //录像
//                                        if( STContext.getInst().videoState == 0 )
//                                            STContext.getInst().videoState = 1;
//                                        else
//                                        if( STContext.getInst().videoState == 1 )
//                                            STContext.getInst().videoState = 0;
//                                        queueEvent(new Runnable() {
//                                            @Override
//                                            public void run(){
//                                                if( mCameraClient != null )
//                                                {
//                                                    if (STContext.getInst().videoState == 1) {
//                                                        if (mCameraClient.isRecording()) {
//                                                            mCameraClient.stopRecording();
//                                                        }
//                                                        mCameraClient.startRecording();
//                                                    } else {
//                                                        if (mCameraClient.isRecording()) {
//                                                            mCameraClient.stopRecording();
//                                                        }
//                                                    }
//                                                }
//                                            }
//                                        }, 0);
                                        onKeyEvent(KeyEvent.KEYCODE_BUTTON_L2);
                                    }
                                });
                                toastAlert( sysPinNum , val , "长按 录像 ts=" + (nowTime - downKeyTime) );
                            }
                            downKeyTime = 0;
                        }
                    }

                    if( sysPinNum == 33 ) {
                        if( leftKeyTime == 0 && val == GPIOEnum.LOW )
                        {
                            leftKeyTime = System.currentTimeMillis();
                            //Log.v(TAG, String.format("GPIO(%d) IN %d ,按下 ", sysPinNum , val ));
                        }
                        else if( leftKeyTime > 0 && val == GPIOEnum.HIGH )
                        {
                            if( nowTime - leftKeyTime < TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
                                    }
                                });
                                toastAlert( sysPinNum , val , "短按 左 ts=" + (nowTime - leftKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 短按 左", sysPinNum , val , nowTime - leftKeyTime ));
                            } else if( nowTime - leftKeyTime >= TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        //菜单
                                        onKeyEvent(KeyEvent.KEYCODE_MENU);
                                    }
                                });
                                toastAlert( sysPinNum , val , "长按 菜单 ts=" + (nowTime - leftKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 长按 菜单", sysPinNum , val , nowTime - leftKeyTime ));
                            }
                            leftKeyTime = 0;
                        }
                    }


                    if( sysPinNum == 36 ) {
                        if( rightKeyTime == 0 && val == GPIOEnum.LOW )
                        {
                            rightKeyTime = System.currentTimeMillis();
                            //Log.v(TAG, String.format("GPIO(%d) IN %d ,按下 ", sysPinNum , val ));
                        }
                        else if( rightKeyTime > 0 && val == GPIOEnum.HIGH )
                        {
                            if( nowTime - rightKeyTime < TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
                                    }
                                });
                                toastAlert( sysPinNum , val , "短按 右 ts=" + (nowTime - rightKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 短按 右", sysPinNum , val , nowTime - rightKeyTime ));
                            } else if( nowTime - rightKeyTime >= TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        //无
                                        //onKeyEvent(KeyEvent.KEYCODE_MENU);
                                    }
                                });
                                toastAlert( sysPinNum , val , "长按 无 ts=" + (nowTime - rightKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 长按 无", sysPinNum , val , nowTime - rightKeyTime ));
                            }
                            rightKeyTime = 0;
                        }
                    }

                    if( sysPinNum == 50 ) {
                        if( centerKeyTime == 0 && val == GPIOEnum.LOW )
                        {
                            centerKeyTime = System.currentTimeMillis();
                            //Log.v(TAG, String.format("GPIO(%d) IN %d ,按下 ", sysPinNum , val ));
                        }
                        else if( centerKeyTime > 0 && val == GPIOEnum.HIGH )
                        {
                            if( nowTime - centerKeyTime < TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onKeyEvent( KeyEvent.KEYCODE_DPAD_CENTER);
                                    }
                                });
                                toastAlert( sysPinNum , val , "短按 确定 ts=" + (nowTime - centerKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 短按 确定", sysPinNum , val , nowTime - centerKeyTime ));
                            } else if( nowTime - centerKeyTime >= TIME_TRICK ) {
                                new Handler( context.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        //返回
                                        onKeyEvent( KeyEvent.KEYCODE_BACK );
                                    }
                                });
                                toastAlert( sysPinNum , val , "长按 返回 ts=" + (nowTime - centerKeyTime) );
                                //Log.v(TAG, String.format("GPIO(%d) IN %d , %d 长按 返回", sysPinNum , val , nowTime - centerKeyTime ));
                            }
                            centerKeyTime = 0;
                        }
                    }
                }
            }
            //Log.v(TAG, "GPIO=" + builder.toString());
        }
    };


    public void onKeyEvent(final int keyCode) {
        new Thread() {
            public void run() {
                try {
                    Instrumentation inst = new Instrumentation();
                    inst.sendKeyDownUpSync(keyCode);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void toastAlert( final  int sysPinNum , final int val , final String note )
    {
        new Handler( context.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                if( DEBUG )
                    Toast.makeText( context , String.format("GPIO(%d) IN %d ," + note , sysPinNum , val ), Toast.LENGTH_SHORT).show();
            }
        });
    }

}
